package com.tensai.study.新特性.JDK8.函数式编程;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class CommonUsage {
    /**
     * 使用lambda表达式对集合进行迭代
     */
    public static void test1() {
        List<String> list = Arrays.asList("java", "c#", "javascript");
        //before java8
        for (String str : list) {
            System.out.println("before java8," + str);
        }
        //after java8
        list.forEach(x -> System.out.println("after java8," + x));
    }

    /**
     * 用lambda表达式实现map
     * <p>
     * map函数可以说是函数式编程里最重要的一个方法了。
     * <p>
     * map的作用是将一个对象变换为另外一个。
     * <p>
     * 在我们的例子中，就是通过map方法将cost增加了0,05倍的大小然后输出。
     */
    public static void test2() {
        List<Double> list = Arrays.asList(10.0, 20.0, 30.0);
        list.stream().map(x -> x + x * 0.05).forEach(System.out::println);
    }

    /**
     * 用lambda表达式实现map与reduce
     * <p>
     * 既然提到了map，又怎能不提到reduce。reduce与map一样，也是函数式编程里最重要的几个方法之一。
     * <p>
     * map的作用是将一个对象变为另外一个，而reduce实现的则是将所有值合并为一个
     */
    public static void test3() {
        //before java8
        List<Double> cost = Arrays.asList(10.0, 20.0, 30.0);
        double sum = 0;
        for (double each : cost) {
            each += each * 0.05;
            sum += each;
        }
        System.out.println("before java8," + sum);
        //after java8
        List<Double> list = Arrays.asList(10.0, 20.0, 30.0);
        double sum2 = list.stream().map(x -> x + x * 0.05).reduce(Double::sum).get();
        System.out.println("after java8," + sum2);
    }

    /**
     * filter操作
     * <p>
     * filter也是我们经常使用的一个操作。
     * <p>
     * 在操作集合的时候，经常需要从原始的集合中过滤掉一部分元素。
     */
    public static void test4() {
        List<Double> cost = Arrays.asList(10.0, 20.0, 30.0, 40.0);
        List<Double> filteredCost = cost.stream().filter(x -> x > 25.0).collect(Collectors.toList());
        filteredCost.forEach(System.out::println);
    }

    /**
     * 与函数式接口Predicate配合
     * <p>
     * 除了在语言层面支持函数式编程风格，Java 8也添加了一个包，叫做 java.util.function。
     * <p>
     * 它包含了很多类，用来支持Java的函数式编程。其中一个便是Predicate，
     * <p>
     * 使用 java.util.function.Predicate 函数式接口以及lambda表达式，可以向API方法添加逻辑，
     * <p>
     * 用更少的代码支持更多的动态行为。
     * <p>
     * Predicate接口非常适用于做过滤。
     */
    public static void test5() {
        List<String> languages = Arrays.asList("Java", "Python", "scala", "Shell", "R");
        filterTest(languages, x -> x.startsWith("J"));//Java
        filterTest(languages, x -> x.endsWith("a"));//Java,scala
        filterTest(languages, x -> true);//Java,Python,scala,Shell,R
        filterTest(languages, x -> false);//
        filterTest(languages, x -> x.length() > 4);//Python,scala,Shell,
    }

    private static void filterTest(List<String> languages, Predicate<String> condition) {
        languages.stream().filter(condition).forEach(x -> System.out.println(x + " "));
    }


}
